# Copyright 2012 Robert Muth
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; version 3
# of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

"""
HocusPocus Plugin "pulse" (pulse audio)
"""
# python imports
import logging
import os
import tornado.web

# local imports
import utils

PACTL = "/usr/bin/pactl"
PACMD = "/usr/bin/pacmd"


if not os.path.exists(PACTL):
    logging.fatal("missing binary %s", PACTL)

if not os.path.exists(PACMD):
    logging.fatal("missing binary %s", PACMD)


def PulseStatus():
    comm = "%s %s" % (PACTL, "stat")
    return utils.RunCommand(comm.split())

def PulseList():
    comm = "%s %s" % (PACTL, "list")
    return utils.RunCommand(comm.split())


def PulseReset():
    comm = "%s %s" % (PACTL, "exit")
    return utils.RunCommand(comm.split())

def PamanCommand(s):
    return utils.RunCommand(PACMD, s)



def ExtractVolume(s):
    tokens = s.split()
    for t in tokens:
        if t.endswith("%"):
            return t[:-1]

class Device:
    def __init__(self, no, lines, is_sink):
        assert no.startswith("#")
        no = no[1:]
        self.description = "no_description"
        self.app_name = "no_name"
        self.volume = "no_volume"
        self.base_volume = "no_volume"
        self.mute = "no_mute"
        self.state = "no_state"
        self.steps = 0
        self.no = no
        self.is_sink = is_sink
        for l in lines:
            l = l.strip()
            if l.startswith("Volume:"):
                # NOTE: ignoring other stere channel
                self.volume = ExtractVolume(l)
            elif l.startswith("Base Volume:"):
                self.base_volume = ExtractVolume(l)
            elif l.startswith("Mute:"):
                self.mute = l.split()[1]
            elif l.startswith("State:"):
                self.state = l.split()[1]
            elif l.startswith("Description:"):
                self.description = l


def GetSinksAndInputs():
    sinks = []
    inputs = []
    _, out = PulseList()
    out = str(out, encoding='utf8' )
    sections = out.split("\n\n")
    logging.info("found %d sections in pulse list", len(sections))
    for s in sections:
        lines =  s.split("\n")
        header = lines.pop(0)
        section_type, no =  header.rsplit(None, 1)
        if section_type == "Sink":
            sinks.append(Device(no, lines, True))
        elif section_type == "Source":
            inputs.append(Device(no, lines, False))
    return sinks, inputs


class Handler(tornado.web.RequestHandler):
    def initialize(self, template_args):
        logging.debug("pulse hander  init")
        self._template_args = template_args
        status = PulseStatus()[1]
        sinks, inputs = GetSinksAndInputs()
        self._template_args["status"] =  status
        self._template_args["inputs"] = inputs
        self._template_args["sinks"] = sinks


    @tornado.web.asynchronous
    def get(self, dummy_p, *dummy_k):
        logging.info("pulse handler request")
        self.write(self.render_string("pulse.html", **self._template_args))
        self.finish()

class CommandHandler(tornado.web.RequestHandler):
    def initialize(self, template_args):
        logging.debug("pulse command handler init")
        self._template_args = template_args


    @tornado.web.asynchronous
    def get(self, dummy_p, *dummy_k):
        command = self.get_argument("command")
        device = self.get_argument("device")
        value = self.get_argument("value")
        logging.info("pulse command handler request [%s]", command)
        if command == "source_mute":
            cmd = "set-source-mute %s %s" % (device, value)
            PamanCommand(cmd)
        elif command == "sink_mute":
            PamanCommand("set-sink-mute %s %s" % (device, value))
        elif command == "source_vol":
            cmd = "set-source-volume %s %d" % (device, int(int(value) * 65536 / 100))
            PamanCommand(cmd)
        elif command == "sink_vol":
            cmd = "set-sink-volume %s %d" % (device, int(int(value) * 65536 / 100))
            PamanCommand(cmd)
        else:
            logging.error("unknown command [%s]", command)
        self.finish()


def GetHandlers():
    return [(r"/pulse/(.*)", Handler),
            (r"/pulse_command(.*)", CommandHandler),
            ]

def GetDependencies():
    return [PACTL, PACMD]

